﻿#pragma once
#include "XyNet/Common/Id.h"
#include <boost/asio.hpp>

namespace XyNet
{
	class RpcArgument;
	class RpcEndpoint;
	class RpcSocketChannel;

	/// rpc回调，保存参数和事件处理，超时控制
	class XYNET_API RpcCallback : noncopyable
	{
	protected:
		RpcCallback(shared_ptr<RpcArgument> argument);

	public:
		virtual ~RpcCallback();

		/// 获取参数
		shared_ptr<RpcArgument> getArgument();

		/// 获取创建时间
		const chrono::steady_clock::time_point& getCreateTime() const;

		/// 处理回调
		void run();

		/// 开始计时器
		void startTimer(RpcSocketChannel* socketChannel, const Id& messageId);
		/// 停止计时器
		void stopTimer();

		/// 要保证多态，需要克隆
		virtual shared_ptr<RpcCallback> clone() = 0;

	private:
		/// 处理回调（子类实现）
		virtual void doResponseHandler() = 0;
		/// 处理异常（子类实现）
		virtual void doExceptionHandler() = 0;

		/// 计时器超时处理
		static void onTimeOut(RpcEndpoint* endpoint, const Id& socketChannelId,
			const Id& messageId, const boost::system::error_code& error);

	protected:
		/// 回调参数
		shared_ptr<RpcArgument> _argument;

		/// 超时控制定时器
		shared_ptr<boost::asio::deadline_timer> _timer;

		/// 回调创建时间
		chrono::steady_clock::time_point _createTime;
	};
}